﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Lidgren.Network;
using Lidgren.Network.Xna;
using Microsoft.Xna.Framework;
using SharedLib.Engine;
using Microsoft.Xna.Framework.Graphics;
using GameStateManagement;

namespace SharedLib.Network.Client
{
    public class ClientListener
    {
        ClientProperties Pbag;
        NetClient Client;
        NetIncomingMessage _msgBuffer;

        public ClientListener(NetClient netc, ClientProperties pb)
        {
            Client = netc;
            Pbag = pb;
        }

        public void Update()
        {
            while ((_msgBuffer = Client.ReadMessage()) != null)
            {
                NetIncomingMessageType msgType = _msgBuffer.MessageType;

                switch (msgType)
                {
                    case NetIncomingMessageType.StatusChanged:
                        {
                        }
                        break;
                    case NetIncomingMessageType.ConnectionApproval:
                        {
                            break;
                        }
                    case NetIncomingMessageType.Data:
                        {
                            SharedLib.Constants.PacketType dataType = (SharedLib.Constants.PacketType)_msgBuffer.ReadByte();
                            switch (dataType)
                            {
                                case Constants.PacketType.ChunkTransfer:

                                    RenderTarget2D minimap = (RenderTarget2D)Pbag.ObjectsBox["minimap"];
                                    ScreenManager ScreenManager = (ScreenManager)Pbag.ObjectsBox["screenmanager"];

                                    ScreenManager.GraphicsDevice.SetRenderTarget(minimap);

                                    ScreenManager.SpriteBatch.Begin();

                                    Vector2 drawPosition = _msgBuffer.ReadVector2();
                                    byte[,] tilesWorld = new byte[3 * Constants.CHUNK_WIDTH, 3 * Constants.CHUNK_HEIGHT];
                                    byte[,] collisionsWorld = new byte[3 * Constants.CHUNK_WIDTH, 3 * Constants.CHUNK_HEIGHT];

                                    for (int x = 0; x < tilesWorld.GetLength(0); x++)
                                    {
                                        for (int y = 0; y < tilesWorld.GetLength(1); y++)
                                        {
                                            tilesWorld[x, y] = _msgBuffer.ReadByte();
                                            ScreenManager.SpriteBatch.Draw(Tile.getTexture(), new Rectangle(x * Constants.MAP_TILE_SIZE, y * Constants.MAP_TILE_SIZE, Constants.MAP_TILE_SIZE, Constants.MAP_TILE_SIZE), Tile.getTileRectangle(tilesWorld[x, y]), Color.White);
                                            collisionsWorld[x, y] = _msgBuffer.ReadByte();
                                        }   
                                    }
                                    
                                    ScreenManager.SpriteBatch.End();
                                    ScreenManager.GraphicsDevice.SetRenderTarget(null);

                                        Engine.Zone myZoneC = new Engine.Zone(tilesWorld.GetLength(0), tilesWorld.GetLength(1));
                                        myZoneC.AmbiantValue = 0.3f;

                                        Engine.Layer backgroundL = new Engine.Layer(tilesWorld.GetLength(0), tilesWorld.GetLength(1), Engine.LayerType.Background);
                                        Engine.Layer collisionL = new Engine.Layer(tilesWorld.GetLength(0), tilesWorld.GetLength(1), Engine.LayerType.Collision);
                                        
                                        backgroundL.Cells = tilesWorld;
                                        collisionL.Cells = collisionsWorld;

                                        backgroundL.cellsToTiles(drawPosition);
                                        collisionL.cellsToTiles(drawPosition);

                                        myZoneC.Layers.Add(backgroundL);
                                        myZoneC.Layers.Add(collisionL);

                                        Pbag.WorldManager.Zone = myZoneC;

                                        Pbag.WorldManager.entitiesList.Clear();
                                        int playerCount = _msgBuffer.ReadInt32();
                                        for (int i = 0; i < playerCount; i++)
                                        {
                                            EntityType type = (EntityType)_msgBuffer.ReadByte();
                                            switch (type)
                                            {
                                                    
                                                case EntityType.Entity:
                                                    break;
                                                case EntityType.Light:
                                                    Light lumiere = new Light();
                                                    lumiere.Side = EntitySide.Client;
                                                    lumiere.ReadData(_msgBuffer);

                                                    KeyValuePair<long, Entity> alreadyLight = Pbag.WorldManager.entitiesList.Where(p => p.Key == lumiere.ID).FirstOrDefault();

                                                    if (alreadyLight.Value == null)
                                                        Pbag.WorldManager.entitiesList.Add(lumiere.ID, lumiere);
                                                    

                                                    break;
                                                case EntityType.Monster:
                                                    Monster mob = new Monster();
                                                    mob.Side = EntitySide.Client;
                                                    mob.ReadData(_msgBuffer);
                                                    KeyValuePair<long, Entity> alreadyMob = Pbag.WorldManager.entitiesList.Where(p => p.Key == mob.ID).FirstOrDefault();

                                                    if (alreadyMob.Value == null)
                                                        Pbag.WorldManager.entitiesList.Add(mob.ID, mob);
                                                    else
                                                    {
                                                        Monster m = (Monster)(Pbag.WorldManager.entitiesList[mob.ID]);
                                                        m.Position = mob.Position;
                                                        m.Rotation = mob.Rotation;
                                                        m.HP = mob.HP;
                                                        m.HPMAX = mob.HPMAX;
                                                        m.Mana = mob.Mana;
                                                        m.ManaMAX = mob.ManaMAX;
                                                    }
                                                    break;
                                                case EntityType.Player:
                                                    ClientPlayer dummy = new ClientPlayer();
                                                    dummy.Side = EntitySide.Client;
                                                    dummy.ReadData(_msgBuffer);
                                                    KeyValuePair<long, Entity> alreadyPlayer = Pbag.WorldManager.entitiesList.Where(p => p.Key == dummy.ID).FirstOrDefault();
                                                    if (alreadyPlayer.Value == null)
                                                        Pbag.WorldManager.entitiesList.Add(dummy.ID, dummy);
                                                    else
                                                    {
                                                        ClientPlayer m = (ClientPlayer)(Pbag.WorldManager.entitiesList[dummy.ID]);
                                                        m.Position = dummy.Position;
                                                        m.Rotation = dummy.Rotation;
                                                        m.HP = dummy.HP;
                                                        m.HPMAX = dummy.HPMAX;
                                                        m.Mana = dummy.Mana;
                                                        m.ManaMAX = dummy.ManaMAX;
                                                    }
                                                    break;
                                                default:
                                                    break;
                                            }

                                            
                                        }

                                        Pbag.State = ClientState.InGame;
                                        GameStateManagement.GameplayScreen.initHulls = false;
                                    break;
                                
                              
                                case SharedLib.Constants.PacketType.PlayerInitialUpdate:
                                    {
                                        _msgBuffer.ReadByte();
                                        Pbag.Player.ReadData(_msgBuffer);
                                        break;
                                    }
                                case SharedLib.Constants.PacketType.EntityJoin:
                                    {
                                        if (Pbag.State == ClientState.InGame)
                                        {
                                            EntityType type = (EntityType)_msgBuffer.ReadByte();
                                            switch (type)
                                            {
                                                case EntityType.Entity:
                                                    break;
                                                case EntityType.Light:
                                                    Light lumiere = new Light();
                                                    lumiere.Side = EntitySide.Client;
                                                    lumiere.ReadData(_msgBuffer);

                                                    KeyValuePair<long, Entity> alreadyLight = Pbag.WorldManager.entitiesList.Where(p => p.Key == lumiere.ID).FirstOrDefault();

                                                    if (alreadyLight.Value == null)
                                                        Pbag.WorldManager.entitiesList.Add(lumiere.ID, lumiere);
                                                    break;
                                                case EntityType.Monster:
                                                     Monster mob = new Monster();
                                                    mob.Side = EntitySide.Client;
                                                    mob.ReadData(_msgBuffer);
                                                    KeyValuePair<long, Entity> alreadyMob = Pbag.WorldManager.entitiesList.Where(p => p.Key == mob.ID).FirstOrDefault();

                                                    if (alreadyMob.Value == null)
                                                        Pbag.WorldManager.entitiesList.Add(mob.ID, mob);
                                                    else
                                                    {
                                                        Monster m = (Monster)(Pbag.WorldManager.entitiesList[mob.ID]);
                                                        m.Position = mob.Position;
                                                        m.Rotation = mob.Rotation;
                                                        m.HP = mob.HP;
                                                        m.HPMAX = mob.HPMAX;
                                                        m.Mana = mob.Mana;
                                                        m.ManaMAX = mob.ManaMAX;
                                                    }
                                                    break;
                                                case EntityType.Player:
                                                    ClientPlayer dummy = new ClientPlayer();
                                                    dummy.Side = EntitySide.Client;
                                                    dummy.ReadData(_msgBuffer);
                                                    Pbag.WorldManager.entitiesList.Add(dummy.ID, dummy);
                                                    break;
                                                default:
                                                    break;
                                            }
                                        }
                                        break;
                                    }
                                case SharedLib.Constants.PacketType.EntityLeft:
                                    {
                                        if (Pbag.State == ClientState.InGame)
                                        {
                                            long id = _msgBuffer.ReadInt64();
                                            Pbag.WorldManager.entitiesList.Remove(id);
                                        }
                                        break;
                                    }
                                case SharedLib.Constants.PacketType.EntityMovementUpdate:
                                    {
                                        if (Pbag.State == ClientState.InGame)
                                        {
                                            long id = _msgBuffer.ReadInt64();
                                            Vector2 move = _msgBuffer.ReadVector2();

                                            Vector2 tmpVelocity = new Vector2(move.X - Pbag.WorldManager.entitiesList[id].Position.X, move.Y - Pbag.WorldManager.entitiesList[id].Position.Y);
                                            //tmpVelocity /= 5;

                                            //Pbag.WorldManager.entitiesList[id].Position = move;
                                            Pbag.WorldManager.entitiesList[id].Velocity = tmpVelocity;
                                        }
                                        break;
                                    }
                                case SharedLib.Constants.PacketType.EntityRotationUpdate:
                                    {
                                        if (Pbag.State == ClientState.InGame)
                                        {
                                            long id = _msgBuffer.ReadInt64();
                                            Pbag.WorldManager.entitiesList[id].Rotation = _msgBuffer.ReadFloat();
                                        }
                                        break;
                                    }
                                default:
                                    {
                                        break;
                                    }
                            }
                        }
                        break;
                }
            }





        }
    }
}
